package com.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.CustomException;
import com.example.dto.SetmealDto;
import com.example.entity.Category;
import com.example.entity.Setmeal;
import com.example.entity.SetmealDish;
import com.example.mapper.SetmealMapper;
import com.example.service.ICategoryService;
import com.example.service.ISetmealDishService;
import com.example.service.ISetmealService;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 套餐 服务实现类
 * </p>
 *
 * @author czx
 * @since 2022-04-28
 */
@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements ISetmealService {
    @Resource
    @Lazy
    ICategoryService categoryService;

    @Resource
    @Lazy
    ISetmealDishService setmealDishService;

    /**
     * 分页查询
     *
     * @param page     页数
     * @param pageSize 页大小
     * @param name     套餐名
     * @return 分页信息
     */
    @Override
    public Page<SetmealDto> page(int page, int pageSize, String name) {
        // 构造分页构造器
        Page<Setmeal> pageInfo = new Page<>(page, pageSize);
        //构造条件构造器
        LambdaQueryWrapper<Setmeal> wrapper = new LambdaQueryWrapper<>();
        //添加过滤条件
        wrapper.like(StringUtils.isNotEmpty(name), Setmeal::getName, name);
        // 添加排序条件,降序排序
        wrapper.orderByDesc(Setmeal::getCreateTime);
        //执行查询
        Page<Setmeal> setmealPage = baseMapper.selectPage(pageInfo, wrapper);

        PageDTO<SetmealDto> setmealDtoPageDTO = new PageDTO<>();

        BeanUtils.copyProperties(setmealPage, setmealDtoPageDTO, "records");
        List<Setmeal> records = setmealPage.getRecords();
        List<SetmealDto> list = records.stream().map((item) -> {
            SetmealDto setmealDto = new SetmealDto();
            Long categoryId = item.getCategoryId();
            BeanUtils.copyProperties(item, setmealDto);

            Category category = categoryService.getById(categoryId);
            if (category != null) {
                String categoryName = category.getName();
                setmealDto.setCategoryName(categoryName);
            }
            return setmealDto;
        }).collect(Collectors.toList());
        setmealDtoPageDTO.setRecords(list);
        return setmealDtoPageDTO;
    }

    /**
     * 保存数据到setmeal表和setmeal_dish表
     *
     * @param setmealDto 数据传输对象
     * @return 是否保存
     */
    @Override
    public boolean saveWithSetmealDish(SetmealDto setmealDto) {
        boolean save = baseMapper.insert(setmealDto) > 0;
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes().stream().peek((item) -> item.setSetmealId(setmealDto.getId().toString())).collect(Collectors.toList());
        boolean saveBatch = setmealDishService.saveBatch(setmealDishes);
        return save && saveBatch;
    }

    /**
     * 根据id从setmeal表和setmeal_dish表进行查询
     *
     * @param id setmeal表的id
     * @return 数据传输对象
     */
    @Override
    public SetmealDto getByIdWithSetmealDish(Long id) {
        SetmealDto setmealDto = new SetmealDto();
        Setmeal setmeal = baseMapper.selectById(id);
        BeanUtils.copyProperties(setmeal, setmealDto);
        Category category = categoryService.getById(setmeal.getCategoryId());
        if (category != null) {
            //添加分类名称
            setmealDto.setCategoryName(category.getName());
        }
        // 添加菜品
        List<SetmealDish> list = setmealDishService.getBySetmealId(id);
        setmealDto.setSetmealDishes(list);
        return setmealDto;
    }

    /**
     * 更新套餐信息
     *
     * @param setmealDto 数据传输对象
     * @return 更新结果
     */
    @Override
    public boolean updateWithSetmealDish(SetmealDto setmealDto) {
        boolean update = baseMapper.updateById(setmealDto) > 0;
        Long setmealId = setmealDto.getId();
        //先删除，再插入
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();

        setmealDishService.removeBySetmealId(setmealId);

        List<SetmealDish> setmealDishList = setmealDishes.stream().peek((item) -> item.setSetmealId(String.valueOf(setmealId))).collect(Collectors.toList());
        boolean saveBatch = setmealDishService.saveBatch(setmealDishList);
        return update && saveBatch;
    }

    /**
     * 套餐状态多次或一次修改
     *
     * @param status 修改状态
     * @param ids    套餐id
     * @return 修改结果
     */
    @Override
    public boolean updateByStatus(int status, Long[] ids) {
        int i = 0;
        for (Long id : ids) {
            Setmeal setmeal = baseMapper.selectById(id);
            setmeal.setStatus(status);
            i += baseMapper.updateById(setmeal);
        }
        return i > 0;
    }

    /**
     * 删除套餐
     *
     * @param ids 套餐id
     * @return 删除结果
     */
    @Override
    @Transactional
    public boolean removeWithSetmealDish(List<Long> ids) {
        LambdaQueryWrapper<Setmeal> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Setmeal::getId, ids);
        //套餐是否正在售卖中
        wrapper.eq(Setmeal::getStatus, 1);
        long count = this.count(wrapper);
        //不能删除，抛出异常
        if (count > 0) {
            throw new CustomException("套餐正在售卖中，不能删除");
        }
        //能删除，先删除套餐表中的数据
        boolean remove = this.removeBatchByIds(ids);

        boolean remove1 = setmealDishService.removeBySetmealIds(ids);
        return remove1 && remove;
    }

    /**
     * 套餐信息

     * @param setmeal 套餐
     * @return 结果
     */
    @Override
    public List<Setmeal> listByIdAndStatus(Setmeal setmeal) {
        LambdaQueryWrapper<Setmeal> wrapper = new LambdaQueryWrapper<>();
        // 售卖状态存在才可以加入条件
        wrapper.eq(setmeal.getStatus() != null, Setmeal::getStatus, setmeal.getStatus());
        wrapper.eq(Setmeal::getCategoryId, setmeal.getCategoryId());
        //加入排序条件
        wrapper.orderByDesc(Setmeal::getUpdateTime);
        return this.list(wrapper);
    }
}
